﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;

namespace Collections.TreeCollections
{
    public abstract class TreeRoot : TreeObject, INonLeaf
    {
        #region Property
        /// <summary>
        /// Children
        /// </summary>
        public INonRoot[] Children
        {
            get { return _children.ToArray<INonRoot>(); }
        }
        /// <summary>
        /// Get root based on id
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public INonRoot this[TreeNodeIdentify index]
        {
            get { return getChild(index); }
        }
        #endregion

        #region Fields
        private FMSet<INonRoot> _children;
        #endregion

        public TreeRoot(TreeNodeIdentify id)
            : base(id)
        {
            _children = new FMSet<INonRoot>();
        }
        /// <summary>
        /// Add Children
        /// </summary>
        /// <param name="child"></param>
        public virtual void AddChild(INonRoot child)
        {
            this._children.Add(child);
            child.Parent = this;
        }
        /// <summary>
        /// Remove Child
        /// </summary>
        /// <param name="child"></param>
        public virtual bool RemoveChild(INonRoot child)
        {
            bool ret = this._children.Remove(child);
            child.Parent = null;
            return ret;
        }
        /// <summary>
        /// get child
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        private INonRoot getChild(TreeNodeIdentify id)
        {
            foreach (INonRoot child in _children)
            {
                TreeObject obj = (TreeObject)child;
                if (obj.ID.Equals(id))
                {
                    return child;
                }
            }
            return null;
        }

        #region Xml Parser
        /// <summary>
        /// To Xml Element
        /// </summary>
        /// <returns></returns>
        public override XElement ToXElem()
        {
            XElement xelem = base.ToXElem();
            foreach (INonRoot child in this.Children)
            {
                TreeObject obj = child as TreeObject;
                if (obj == null)
                {
                    continue;
                }

                xelem.Add(obj.ToXElem());
            }

            return xelem;
        }
        /// <summary>
        /// Xml Parser
        /// </summary>
        /// <param name="xelem"></param>
        /// <returns></returns>
        public static void XmlParser(XElement xelem, TreeRegisterClass treeRegister
            , TreeRoot root)
        {
            // construct tree root children
            foreach (XElement tmpXElem in xelem.Elements())
            {
                TreeObject tmpObj = TreeObject.XmlParser(tmpXElem, treeRegister);
                if (tmpObj == null || !(tmpObj is INonRoot))
                {
                    continue;
                }

                if (tmpObj is TreeNode)
                {
                    TreeNode node = (TreeNode)tmpObj;
                    TreeNode.XmlParser(tmpXElem, treeRegister, node);
                }
                else if (tmpObj is TreeLeaf)
                {
                    TreeLeaf leaf = (TreeLeaf)tmpObj;
                    TreeLeaf.XmlParser(tmpXElem, treeRegister, leaf);
                }

                root.AddChild((INonRoot)tmpObj);
                //root.TreeOwner.AddInstance(root, (INonRoot)tmpObj);
            }
        }
        #endregion

        #region Equals
        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public override bool Equals(object obj)
        {
            bool flag = base.Equals(obj);
            if (flag == false)
            {
                return false;
            }
            TreeRoot node = obj as TreeRoot;
            if (node == null)
            {
                return false;
            }
            // contain same children
            FMSet<INonRoot> child = new FMSet<INonRoot>(this.Children);
            FMSet<INonRoot> tmpChild = new FMSet<INonRoot>(node.Children);

            return child.Equals(tmpChild);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public override int GetHashCode()
        {
            return base.GetHashCode();
        } 
        #endregion

        /// <summary>
        /// Whether contian the child
        /// </summary>
        /// <param name="child"></param>
        /// <returns></returns>
        public bool ContainChild(INonRoot child)
        {
            foreach (INonRoot c in _children)
            {
                if (ReferenceEquals(c, child))
                {
                    return true;
                }
            }
            return false;
        }
    }
}
